package com.pine.common.database.config;

import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusPropertiesCustomizer;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.pine.common.database.constant.SupportedInnerInterceptorEnum;
import com.pine.common.database.filter.DruildSqlSlf4jLogFilter;
import com.pine.common.database.interceptor.CustomDataChangeRecorderInnerInterceptor;
import com.pine.common.database.interceptor.MybatisPlusSensitiveInterceptor;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;
import java.util.List;
import java.util.Set;

/**
 * mybatis plus 配置
 *
 * @author pine manage
 * @since 2024-08-09
 */
@Configuration
@Slf4j
@EnableConfigurationProperties({MybatisPlusCustomProperties.class, DataChangedRecordProperties.class})
public class MybatisPlusConfig {

    @Resource
    private MybatisPlusCustomProperties mybatisPlusCustomProperties;

    @Resource
    private DataChangedRecordProperties dataChangedRecordProperties;

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

        // 加载inner拦截器
        List<SupportedInnerInterceptorEnum> innerInterceptors = mybatisPlusCustomProperties.getInnerInterceptors();
        if (CollectionUtils.isNotEmpty(innerInterceptors)) {
            for (SupportedInnerInterceptorEnum innerInterceptor : innerInterceptors) {
                // 如果启动了数据变更记录拦截器
                if (SupportedInnerInterceptorEnum.DATA_CHANGE_RECORDER_INNER_INTERCEPTOR.equals(innerInterceptor)) {
                    // 跳过的mapperStatementId
                    Set<String> statementIdSet = dataChangedRecordProperties.getSkipMappedStatementIdSet();
                    if (ObjectUtils.isNotEmpty(statementIdSet)) {
                        CustomDataChangeRecorderInnerInterceptor.appendSkipMappedStatementIdSet(statementIdSet);
                    }

                    // 跳过的表名
                    Set<String> skipTableNameSet = dataChangedRecordProperties.getSkipTableNameSet();
                    if (ObjectUtils.isNotEmpty(skipTableNameSet)) {
                        CustomDataChangeRecorderInnerInterceptor.appendSkipTableNameSet(skipTableNameSet);
                    }
                }

                // 如果启动了加密拦截器
                if (SupportedInnerInterceptorEnum.MYBATIS_PLUS_SENSITIVE_INTERCEPTOR.equals(innerInterceptor)) {
                    MybatisPlusSensitiveInterceptor.setSensitiveTextKey(mybatisPlusCustomProperties.getSensitiveTextKey());
                    MybatisPlusSensitiveInterceptor.setSensitiveTextPrefix(mybatisPlusCustomProperties.getSensitiveTextPrefix());
                }

                log.info("mybatis-plus注册inner拦截器：{}", innerInterceptor.getDesc());
                interceptor.addInnerInterceptor(innerInterceptor.getInterceptor());
            }
        }
        return interceptor;
    }

    @Bean
    public MybatisPlusPropertiesCustomizer mybatisPlusPropertiesCustomizer() {
        return properties -> {
            GlobalConfig globalConfig = properties.getGlobalConfig();
            globalConfig.setBanner(false);
            globalConfig.setSqlInjector(new BatchColumnSqlInjector());
        };
    }


    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource.druid")
    public DataSource masterDataSource(@Autowired DataSourceProperties dataSourceProperties) {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(dataSourceProperties.getUrl());
        dataSource.setUsername(dataSourceProperties.getUsername());
        dataSource.setPassword(dataSourceProperties.getPassword());
        dataSource.setDriverClassName(dataSourceProperties.getDriverClassName());

        // 打印sql
        if (mybatisPlusCustomProperties.getPrintSql()) {
            List<Filter> proxyFilters = dataSource.getProxyFilters();
            proxyFilters.add(new DruildSqlSlf4jLogFilter());
        }
        return dataSource;
    }


    /**
     * 批量插入
     */
    private static class BatchColumnSqlInjector extends DefaultSqlInjector {
        @Override
        public List<AbstractMethod> getMethodList(org.apache.ibatis.session.Configuration configuration, Class<?> mapperClass, TableInfo tableInfo) {
            List<AbstractMethod> methodList = super.getMethodList(configuration, mapperClass, tableInfo);
            methodList.add(new InsertBatchSomeColumn());
            return methodList;
        }
    }
}
